﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Script.Serialization;

namespace MASAS.MSM.SharePoint.REST.Utils
{

    /// <summary>
    /// Class SPList.
    /// </summary>
    internal class SPList
    {

        /// <summary>
        /// Gets or sets the identifier.
        /// </summary>
        /// <value>The identifier.</value>
        internal string Id { get; set; }

        /// <summary>
        /// Gets or sets the title.
        /// </summary>
        /// <value>The title.</value>
        internal string Title { get; set; }

        /// <summary>
        /// Gets or sets the type of the list item entity.
        /// </summary>
        /// <value>The type of the list item entity.</value>
        internal string ListItemEntityType { get; set; }

        /// <summary>
        /// Gets the items.
        /// </summary>
        /// <value>The items.</value>
        internal List<SPListItem> Items { get { return GetItems(); } }

        /// <summary>
        /// Gets the web.
        /// </summary>
        /// <value>The web.</value>
        internal SPWeb Web { get; private set; }

        /// <summary>
        /// Initializes a new instance of the <see cref="SPList"/> class.
        /// </summary>
        /// <param name="web">The web.</param>
        internal SPList( SPWeb web )
        {
            this.Web = web;
        }

        /// <summary>
        /// Creates the specified web.
        /// </summary>
        /// <param name="web">The web.</param>
        /// <param name="attributes">The attributes.</param>
        /// <returns>SPList.</returns>
        internal static SPList Create( SPWeb web, Dictionary<string,object> attributes )
        {
            SPList newList = new SPList( web );

            object tempObject;
            if( attributes.TryGetValue( "Title", out tempObject ) )
            {
                newList.Title = tempObject as string;
            }
            if( attributes.TryGetValue( "Id", out tempObject ) )
            {
                newList.Id = tempObject as string;
            }
            if( attributes.TryGetValue( "ListItemEntityTypeFullName", out tempObject ) )
            {
                newList.ListItemEntityType = tempObject as string;
            }

            return newList;
        }

        /// <summary>
        /// Gets the items.
        /// </summary>
        /// <returns>List&lt;SPListItem&gt;.</returns>
        private List<SPListItem> GetItems()
        {
            List<SPListItem> items = null;

            string response = SPHelper_REST.RequestData( Web.Url + "/_api/web/lists(guid'"+ Id + "')/items", Web.ConfigData );
            items = ParseItems( response );

            return items;
        }

        /// <summary>
        /// Parses the items.
        /// </summary>
        /// <param name="response">The response.</param>
        /// <returns>List&lt;SPListItem&gt;.</returns>
        private List<SPListItem> ParseItems( string response )
        {
            List<SPListItem> items = new List<SPListItem>();

            JavaScriptSerializer jsSerializer = new JavaScriptSerializer();
            Dictionary<string, object> root = jsSerializer.Deserialize<Dictionary<string, object>>( response );

            object tempObject;
            if( root != null && root.TryGetValue( "d", out tempObject ) && tempObject is Dictionary<string, object> )
            {
                Dictionary<string,object> data = tempObject as Dictionary<string, object>;

                if( data != null && data.TryGetValue( "results", out tempObject ) && tempObject is ArrayList )
                {
                    ArrayList results = tempObject as ArrayList;

                    foreach( object item in results )
                    {
                        if( item is Dictionary<string, object> )
                        {
                            Dictionary<string, object> listItemObject = item as Dictionary<string, object>;

                            SPListItem listItem = SPListItem.Create( listItemObject );
                            items.Add( listItem );
                        }

                    }
                }
            }

            return items;
        }

        /// <summary>
        /// Gets the item by identifier.
        /// </summary>
        /// <param name="itemId">The item identifier.</param>
        /// <returns>SPListItem.</returns>
        internal SPListItem GetItemById( int itemId )
        {
            SPListItem listItem = null;

            string query = "ID eq '" + itemId.ToString() + "'";
            List<SPListItem> results = GetItemsByQuery( query );

            if( results.Count > 0 )
            {
                listItem = results[0];
            }

            return listItem;
        }

        /// <summary>
        /// Gets the item by unique identifier.
        /// </summary>
        /// <param name="itemId">The item identifier.</param>
        /// <returns>SPListItem.</returns>
        internal SPListItem GetItemByUniqueId( Guid itemId )
        {
            SPListItem listItem = null;

            string query = "GUID eq '" + itemId.ToString() + "'";
            List<SPListItem> results = GetItemsByQuery( query );

            if( results.Count > 0 ) {
                listItem = results[0];
            }

            return listItem;
        }

        /// <summary>
        /// Gets the items by query.
        /// </summary>
        /// <param name="query">The query.</param>
        /// <returns>List&lt;SPListItem&gt;.</returns>
        internal List<SPListItem> GetItemsByQuery( string query )
        {
            List<SPListItem> listItems = null;

            string url = Web.Url + "/_api/web/lists(guid'" + this.Id + "')/items?$filter=" + query;
            string response = SPHelper_REST.RequestData( url, Web.ConfigData );

            listItems = ParseItems( response );

            return listItems;
        }

        /// <summary>
        /// Adds the new item.
        /// </summary>
        /// <param name="newItem">The new item.</param>
        /// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
        internal bool AddNewItem( SPListItem newItem )
        {
            bool retValue = false;

            string postUrl = Web.Url + "/_api/web/lists/GetByTitle('" + this.Title + "')/items";
            string postData = newItem.ToJSON();

            string response = SPHelper_REST.PostData( postUrl, postData, Web.ConfigData, Web.ClientContext.FormDigest );

            if( response.Contains( this.ListItemEntityType ) )
            {
                retValue = true;
            }

            return retValue;
        }

        /// <summary>
        /// Updates the item.
        /// </summary>
        /// <param name="listItem">The list item.</param>
        /// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
        internal bool UpdateItem( SPListItem listItem )
        {
            bool retValue = false;

            string postUrl = Web.Url + "/_api/web/lists/GetByTitle('" + this.Title + "')/items(" + listItem.ID.ToString() + ")";
            string postData = listItem.ToJSON();

            retValue = SPHelper_REST.UpdateData( postUrl, postData, Web.ConfigData, Web.ClientContext.FormDigest );

            return retValue;
        }

    }

}
